﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace InstallNDiTunes
{
    /// <summary>
    /// 一个简单的文本日志类
    /// </summary>
    class Logger
    {
        private StreamWriter logWriter = null;
        private int processID = 0;

        private readonly string LogFileName = "InstallNDiTunes_{0}.log";

        #region --- ctor(单例) ---

        private static Logger instance = null;
        private static readonly object locker = new object();

        private Logger()
        {
            try
            {
                this.processID = System.Diagnostics.Process.GetCurrentProcess().Id;
                string logFilePath = string.Format(LogFileName, DateTime.Now.ToString("yyyyMMdd_HHmmss"));
                if(!File.Exists(logFilePath))
                {
                    //this.logWriter = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + logFilePath);
                    this.logWriter = new StreamWriter(Path.GetTempPath() + logFilePath);
                    this.logWriter.AutoFlush=true;

                    this.Begins("InstallNDiTunes Begins");
                }
            }
            catch (Exception e)
            {
                this.LogVerboseExceptionInfo(e);
            }
        }

        public static Logger GetInstance()
        {
            if (instance == null)
            {
                lock (locker)
                {
                    if (instance == null)
                    {
                        instance = new Logger();
                    }
                }
            }
            return instance;
        }

        #endregion

        #region --- private ---

        private void LogStack()
        {
            try
            {
                var trace = new System.Diagnostics.StackTrace();
                foreach (var frame in trace.GetFrames())
                {
                    var method = frame.GetMethod();
                    if (method.Name.Equals("LogStack")) continue;
                    this.PrintInfoLine(string.Format("MethodName: {0} ", frame.GetMethod()));
                }
            }
            catch 
            {
            }
        }

        private void PrintSeparatorLine()
        {
            try
            {
                string separator = string.Format("[{0} @ {1} ]   {2}", this.processID, this.FormattedDateNow,
              new StringBuilder().Append('=', 36));
                this.logWriter.WriteLine(separator);
            }
            catch 
            {
            }
          
        }

        private void PrintInfoLine(string info)
        {
            try
            {
                string infoLine = string.Format("[{0} @ {1} ]       {2}", this.processID, this.FormattedDateNow, info);
                this.logWriter.WriteLine(infoLine);
            }
            catch 
            {
            }
           
        }

        private string FormattedDateNow
        {
            get
            {
                return DateTime.Now.ToString("R");
            }
        }

        #endregion
                
        #region --- log function ---

        /// <summary>
        /// 开始某项功能
        /// </summary>
        /// <param name="function">功能名字,描述等</param>
        public void Begins(string function)
        {
            this.PrintSeparatorLine();
            this.PrintInfoLine(function);
            this.PrintSeparatorLine();
        }

        public void Ends(string function)
        {
            this.Begins(function);
        }

        public void LogExceptionInfo(Exception e)
        {
            this.LogStack();
            this.PrintInfoLine(string.Format("Message:\t{0}", e.Message));
            this.PrintInfoLine(string.Format("StackTrace:\t{0}", e.StackTrace));
        }

        public void LogVerboseExceptionInfo(Exception e)
        {
            this.LogVerboseExceptionInfo(e, false);
        }

        private void LogVerboseExceptionInfo(Exception e, bool isInnerException)
        {
            if (!isInnerException)
                this.LogStack();
            if (isInnerException)
                this.PrintInfoLine("****** InnerException Messages ******");

            this.PrintInfoLine(string.Format("Message:\t{0}", e.Message));
            this.PrintInfoLine(string.Format("StackTrace:\t{0}", e.StackTrace));
            this.PrintInfoLine(string.Format("TargetSite:\t{0}", e.TargetSite));
            this.PrintInfoLine(string.Format("Source:\t{0}", e.Source));

            if (!isInnerException)
            {
                if (e.InnerException != null)
                    this.LogVerboseExceptionInfo(e.InnerException, true);
            }
        }

        public void LogInfo(string info)
        {
            this.PrintInfoLine(info);
        }

        #endregion

    }
}
